#include <iostream>
#include <memory>
#include <string>
#include <functional>
#include <sstream>
#include <string>
#include <fstream>
using namespace std;

template<class T>
class Auto_ptr
{
public:
    Auto_ptr(T* ptr = nullptr):_ptr(ptr){}
    ~Auto_ptr()
    {
        delete _ptr;
        _ptr = nullptr;
    }
    Auto_ptr(Auto_ptr<T>& ptr)
    {
        _ptr = ptr._ptr;
        ptr._ptr = nullptr;
    }
    Auto_ptr<T> operator=(Auto_ptr<T>& ptr)
    {
        if(_ptr != nullptr)
        {
            delete _ptr;
            _ptr = ptr._ptr;
            ptr._ptr = nullptr;
        } 
        return *this;
    }
    T& operator*()
    {
        return *_ptr;
    }
    T* operator->()
    {
        return _ptr;
    }
private:
    T* _ptr = nullptr;
};

template<class T>
class Unique_ptr
{
public:
    Unique_ptr(T* ptr = nullptr):_ptr(ptr) {}
    ~Unique_ptr()
    {
        if(_ptr != nullptr)
        {
            delete _ptr;
            _ptr = nullptr;
        }
    }
    T& operator*()
    {
        return *_ptr;
    }
    T* operator->()
    {
        return _ptr;
    }
private:
    Unique_ptr(Unique_ptr<T>& ptr) = delete;
    Unique_ptr<T>& operator=(Unique_ptr<T>& ptr) = delete;

private:
    T* _ptr;
};

template<class T>
struct default_delete
{
    void operator()(T* ptr)
    {
        delete ptr;
    }
};
//针对new[]的释放
template<class T>
struct DeleteArray
{
    void operator()(T* ptr)
    {
        cout << "delete[]" << ptr << endl;
        delete[] ptr;
    }
};
//针对malloc的释放
template<class T>
struct Free
{
    void operator()(T* ptr)
    {
        cout << "free" << ptr << endl;
        free(ptr);
    }
};
//针对fopen的释放
struct Fclose
{
    void operator()(FILE* ptr)
    {
        cout << "fclose" << ptr << endl;
        fclose(ptr);
    }
};

template<class T>
class Shared_ptr
{
public:
    // template<class D>
    Shared_ptr(T* ptr = nullptr): _ptr(ptr),_count(new int(1)){}
    ~Shared_ptr()
    {
        (*_count) -= 1;
        if(*_count == 0)
        {
            if(_ptr != nullptr)
            {    
                delete _ptr;
                _ptr = nullptr;
            }
            delete _count;
            _count = nullptr;
        }
    }
    Shared_ptr(Shared_ptr<T>& ptr)
    {
        _ptr = ptr._ptr;
        _count = ptr._count;
        (*_count)++;
    }
    Shared_ptr<T>& operator=(Shared_ptr<T>& ptr)
    {
        if(_ptr != nullptr)
        {
            if(--(*_count) == 0)
            {
                delete _ptr;
                delete _count;
            }
            _ptr = ptr._ptr;
            _count = ptr._count;
            (*_count)++;
        }
        return *this;
    }
    T& operator*()
    {
        return *_ptr;
    }
    T* operator->()
    {
        return _ptr;
    }
private:
    T* _ptr;
    int* _count;

    function<void(T*)> _del;
};

template<class T>
class Week_ptr
{
    Week_ptr(T* ptr = nullptr):_ptr(ptr){}
    ~Week_ptr()
    {
        
        if(_ptr != nullptr)
        {
            delete _ptr;
            _ptr == nullptr;
        }
    }
    Week_ptr(Week_ptr<T>& ptr)
    {
        _ptr = ptr._ptr;
    }
    Week_ptr(Shared_ptr<T>& ptr)
    {
        _ptr = ptr._ptr;
    }
    Week_ptr<T>& operator=(Shared_ptr<T>& ptr)git
    {
        _ptr = ptr._ptr;
    }
private:
    T* _ptr;
}; 

void test()
{
    // string x;
    // cin >> x;
    // if(x == "yes")
    // {
        
    // }
}
int main()
{
    // Auto_ptr<int> x(new int(1));
    // Auto_ptr<int> y(new int(2));
    // x = y;

    // Shared_ptr<int> x(new int(1));
    // Shared_ptr<int> y(new int(3));
    // x = y;
    // y = x;
    // cout << *x << endl;
    // cout << *y << endl;

    //shared_ptr<string> s1(new string());
    // s1[0] = "hello wr";
    //s1->push_back('?');
    // cout << *s1 << endl;
    //cout <<  << endl;
    
    // **s1 = 1;
    // (*s1)[1] = 1;
    // cout << **s1 << endl;
    // cout << (*s1)[1] << endl;

    // shared_ptr<int> s2(new int[10](),[](int* ptr){ delete[] ptr;});
    // s2.get()[0]=1;
    // s2.get()[1]=1;
    // s2.get()[2]=1;
    // s2.get()[3]=1;
    // cout << s2.get()[3] << endl;
    // std::shared_ptr<int> sp4((int*)malloc(sizeof(int) * 10), [](int* ptr){ free(ptr); });//传仿函数的匿名对象释放
    // s2.get()[0]=1;
    // s2.get()[1]=1;
    // s2.get()[2]=1;
    // *(s2+1)

    // int n = 10;
	// string str;
	// stringstream ss;
	// ss << n; //将int类型的n放入输入流
	// ss >> str; //从ss中抽取前面插入的int类型的值，赋值给string类型（方式一）
	// cout << str << endl;//10
	// ss.str(""); //将stringstream底层管理的string对象设置为""。
	// ss.clear(); //将上次转换状态清空掉
	// //进行下一次转换
	// double b = 44.55;
	// ss << b;
	// str = ss.str(); //获取stringstream中管理的string类型（方式二）
	// cout << str << endl;//44.55
    // int c = 100;
    // cout << to_string(c) << endl;

    //ofstream file("");
    // printf("hello word\n");
    return 0;
}